package com.linkgie.galaxyframework.utils;

import java.security.SecureRandom;

/**
 * 基于 {@link SecureRandom} 的随机数生成工具类；
 * 
 * @author Hike
 *
 */
public class SecureRandomUtils {

	/**
	 * 生成指定长度的随机数；
	 * 
	 * @param size
	 * @return
	 */
	public static byte[] generate(int size) {
		SecureRandom rng = new SecureRandom();
		byte[] randomBytes = new byte[size];
		rng.nextBytes(randomBytes);
		return randomBytes;
	}

	/**
	 * 用指定的种子生成秘钥；
	 * <p>
	 * 
	 * 注：需要注意，同一个种子有可能产生不同的随机数序列；
	 * 
	 * @param size 要输出的随机数的长度；（单位：字节）
	 * @param seed 随机种子；
	 * @return 随机数；长度等于 sizeOfRandom 参数指定的值；
	 */
	public static byte[] generate(int size, byte[] seed) {
		SecureRandom rng = null;
		if (seed == null || seed.length == 0) {
			// 随机；
			rng = new SecureRandom();
		} else {
			rng = new SecureRandom(seed);
		}
		byte[] randomBytes = new byte[size];
		rng.nextBytes(randomBytes);
		return randomBytes;
	}

	/**
	 * 生成随机的32位整数；
	 * 
	 * @return
	 */
	public static int generateInt() {
		SecureRandom rng = new SecureRandom();
		byte[] randomBytes = new byte[4];
		rng.nextBytes(randomBytes);
		return BinaryUtils.toInt(randomBytes);

		// 注：避免使用 rng.nextInt() 方法，因为它采用的是由 Random.nextInt 实现的伪随机数，安全强度不够；
		// return rng.nextInt();

	}

	/**
	 * 生成 0 和指定值之间的随机正整数；
	 * 
	 * @param bound 随机数的最大值；必须是正整数；
	 * @return
	 */
	public static int generateInt(int bound) {
		if (bound <= 0) {
			throw new IllegalArgumentException("bound must be positive");
		}
		SecureRandom rng = new SecureRandom();
		//TODO: 避免使用 rng.nextInt() 方法，因为它采用的是由 Random.nextInt 实现的伪随机数，安全强度不够；
		return rng.nextInt(bound);
	}

	/**
	 * 生成 64 位整数；
	 * 
	 * @return
	 */
	public static long generateLong() {
		SecureRandom rng = new SecureRandom();
		return rng.nextLong();
	}

}
